package com.settlement.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.settlement.system.common.constant.SystemConstants;
import com.settlement.system.common.model.Option;
import com.settlement.system.common.util.StringUtils;
import com.settlement.system.model.entity.SysAccessory;
import com.settlement.system.model.entity.SysCompany;
import com.settlement.system.model.entity.SysSubjects;
import com.settlement.system.mapper.SysSubjectsMapper;
import com.settlement.system.model.form.SubjectsForm;
import com.settlement.system.model.query.SubjectsPageQuery;
import com.settlement.system.model.vo.SubjectsImportVo;
import com.settlement.system.model.vo.SysSubjectsVO;
import com.settlement.system.service.SysAccessoryService;
import com.settlement.system.service.SysCompanyService;
import com.settlement.system.service.SysDictService;
import com.settlement.system.service.SysSubjectsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 科目设置 服务实现类
 * </p>
 *
 * @author huangrensen
 * @since 2023-09-07
 */
@Service
@RequiredArgsConstructor
public class SysSubjectsServiceImpl extends ServiceImpl<SysSubjectsMapper, SysSubjects> implements SysSubjectsService {

    private final SysCompanyService sysCompanyService;

    private final SysDictService sysDictService;

    private final SysAccessoryService sysAccessoryService;

    private final RedisTemplate redisTemplate;

    @Override
    public Page<SysSubjectsVO> getSubjectsPage(SubjectsPageQuery queryParams) {
        // 查询参数
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();
        String keywords = queryParams.getKeywords();
        // 查询数据
        Page<SysSubjects> subjectsPage = this.page(new Page<>(pageNum, pageSize),
                new LambdaQueryWrapper<SysSubjects>().like(StrUtil.isNotBlank(keywords), SysSubjects::getFirstCode, keywords)
                        .or().like(StrUtil.isNotBlank(keywords), SysSubjects::getFirstName, keywords)
                        .or().like(StrUtil.isNotBlank(keywords), SysSubjects::getLastCode, keywords)
                        .or().like(StrUtil.isNotBlank(keywords), SysSubjects::getLastName, keywords)
                        .orderByDesc(SysSubjects::getUpdateTime));
        Page<SysSubjectsVO> page = new Page<>();
        BeanUtil.copyProperties(subjectsPage, page, "records");
        List<SysSubjectsVO> sysSubjectsVOS = new ArrayList<>();
        if (subjectsPage.getRecords().size() > 0) {
            List<SysCompany> sysCompanyList = sysCompanyService.list();
            for (SysSubjects record : subjectsPage.getRecords()) {
                SysSubjectsVO vo = new SysSubjectsVO();
                BeanUtil.copyProperties(record, vo);
                sysCompanyList.stream().filter(sysCompany -> sysCompany.getCode().equals(record.getCompanyCode())).findFirst().ifPresent(sysCompany -> vo.setCompanyName(sysCompany.getName()));
                sysSubjectsVOS.add(vo);
            }
        }
        page.setRecords(sysSubjectsVOS);
        return page;
    }

    @Override
    @SuppressWarnings("unchecked")
    public boolean saveSubjects(SubjectsForm subjectsForm) {
        if (subjectsForm.getId() == null) {
            long count = this.count(new LambdaQueryWrapper<SysSubjects>()
                    .eq(SysSubjects::getLastCode, subjectsForm.getLastCode())
            );
            Assert.isTrue(count == 0, "末级科目编码【%s】已存在".formatted(subjectsForm.getLastCode()));
        } else {
            long count = this.count(new LambdaQueryWrapper<SysSubjects>()
                    .eq(SysSubjects::getLastCode, subjectsForm.getLastCode())
                    .ne(SysSubjects::getId, subjectsForm.getId())
            );
            Assert.isTrue(count == 0, "末级科目编码【%s】已存在".formatted(subjectsForm.getLastCode()));
        }
        SysSubjects sysSubjects;
        if (subjectsForm.getId() != null) {
            sysSubjects = this.getById(subjectsForm.getId());
        } else {
            sysSubjects = new SysSubjects();
        }
        BeanUtil.copyProperties(subjectsForm, sysSubjects, "id");
        // 删除缓存
        redisTemplate.delete(SystemConstants.SUBJECTS_PREFIX+sysSubjects.getLastCode());
        return this.saveOrUpdate(sysSubjects);
    }

    @Override
    public SysSubjects getSubjectsFormData(Long subjectsId) {
        return this.getById(subjectsId);
    }

    @Override
    @SuppressWarnings("unchecked")
    public boolean deleteSubjects(String idsStr) {
        Assert.isTrue(StrUtil.isNotBlank(idsStr), "删除的科目表数据为空");
        List<Long> ids = Arrays.stream(idsStr.split(",")).map(Long::parseLong).collect(Collectors.toList());
        List<SysSubjects> list = this.list(new LambdaQueryWrapper<SysSubjects>()
                .eq(SysSubjects::getId, ids));
        for (SysSubjects sysSubjects : list) {
            // 删除缓存
            redisTemplate.delete(SystemConstants.SUBJECTS_PREFIX+sysSubjects.getLastCode());
        }
        return this.removeByIds(ids);
    }

    @Override
    public List<SysSubjects> getSubjectsList(SubjectsPageQuery queryParams) {
        if (!StringUtils.hasText(queryParams.getKeywords())) {
            return this.page(new Page<>(1, 50), new LambdaQueryWrapper<>()).getRecords();
        }
        return this.page(new Page<>(1, 50), new LambdaQueryWrapper<SysSubjects>().like(SysSubjects::getLastCode,
                queryParams.getKeywords())).getRecords();
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<String> updateBatch(List<SubjectsImportVo> vos) {
        List<String> messages = new ArrayList<>();
        // 入账主体
        List<SysCompany> sysCompanyList = sysCompanyService.list();
        // 记账科目
        List<Option> options = sysDictService.listDictOptions("jzxmmc");
        // 辅助项
        List<SysAccessory> sysAccessoryList = sysAccessoryService.findAll();
        if (sysAccessoryList == null || sysAccessoryList.size() == 0) {
            messages.add("系统没有配置到辅助项，导入失败");
            return messages;
        }
        SysAccessory accessory = sysAccessoryList.get(0);
        List<String> accessoryTextList = new ArrayList<>();
        if (StringUtils.hasText(accessory.getAccessoryName1())) {
            accessoryTextList.add(accessory.getAccessoryName1());
        }
        if (StringUtils.hasText(accessory.getAccessoryName2())) {
            accessoryTextList.add(accessory.getAccessoryName2());
        }
        if (StringUtils.hasText(accessory.getAccessoryName3())) {
            accessoryTextList.add(accessory.getAccessoryName3());
        }
        if (StringUtils.hasText(accessory.getAccessoryName4())) {
            accessoryTextList.add(accessory.getAccessoryName4());
        }
        if (StringUtils.hasText(accessory.getAccessoryName5())) {
            accessoryTextList.add(accessory.getAccessoryName5());
        }
        if (StringUtils.hasText(accessory.getAccessoryName6())) {
            accessoryTextList.add(accessory.getAccessoryName6());
        }
        if (StringUtils.hasText(accessory.getAccessoryName7())) {
            accessoryTextList.add(accessory.getAccessoryName7());
        }
        if (StringUtils.hasText(accessory.getAccessoryName8())) {
            accessoryTextList.add(accessory.getAccessoryName8());
        }
        if (StringUtils.hasText(accessory.getAccessoryName9())) {
            accessoryTextList.add(accessory.getAccessoryName9());
        }
        List<SysSubjects> createList = new ArrayList<>();
        String accessoryNames;
        String[] accessoryNameArray;
        List<String> accessoryNameList;
        List<String> borrowingList = Arrays.asList("借", "贷");
        for (SubjectsImportVo vo : vos) {
            if (StringUtils.hasText(vo.getBorrowing())) {
                if (!borrowingList.contains(vo.getBorrowing())) {
                    messages.add("借贷方向有以下两个值：借、贷。请调整表格数据");
                }
            } else {
                messages.add("借贷方向一列不能为空");
            }
            SysSubjects sysSubjects = new SysSubjects();
            BeanUtil.copyProperties(vo, sysSubjects, "companyCode", "accountingProject");
            SysCompany company = sysCompanyList.stream().filter(sysCompany -> sysCompany.getName().equals(vo.getCompanyName()))
                    .findFirst()
                    .orElse(null);
            if (company == null) {
                messages.add("系统没维护入账主体【%s】".formatted(vo.getCompanyName()));
            } else {
                sysSubjects.setCompanyCode(company.getCode());
            }
            if (!StringUtils.hasText(vo.getBillProject())) {
                messages.add("记账项目不能为空");
            }else {
                vo.setBillProject(vo.getBillProject().trim());
                Option billProject = options.stream().filter(option -> option.getValue().equals(vo.getBillProject())).findFirst().orElse(null);
                if (billProject == null) {
                    messages.add("系统没维护记账项目【%s】".formatted(vo.getBillProject()));
                } else {
                    sysSubjects.setAccountingProject(vo.getBillProject());
                }
            }
            if (StringUtils.hasText(vo.getAccessory())) {
                accessoryNames = vo.getAccessory().replaceAll(" ", "").replaceAll("，", ",");
                accessoryNameArray = accessoryNames.split(",");
                accessoryNameList = new ArrayList<>();
                for (String accessoryText : accessoryNameArray) {
                    if (!accessoryTextList.contains(accessoryText)) {
                        messages.add("系统不存在辅助项【%s】".formatted(accessoryText));
                    } else {
                        accessoryNameList.add(accessoryText);
                    }
                }
                sysSubjects.setAccessoryNames(String.join(",", accessoryNameList));
            }
            createList.add(sysSubjects);
        }
        if (messages.size() == 0) {
            for (SysSubjects sysSubjects : createList) {
                this.saveOrUpdate(sysSubjects);
                // 删除缓存
                redisTemplate.delete(SystemConstants.SUBJECTS_PREFIX+sysSubjects.getLastCode());
            }
        }
        return messages;
    }

    @Override
    @SuppressWarnings("unchecked")
    public SysSubjects getByLastCode(String lastCode) {
        Object value = redisTemplate.opsForValue().get(SystemConstants.SUBJECTS_PREFIX+lastCode);
        if(value != null){
            return (SysSubjects)value;
        }
        // 因为不同入账主体的末级科目编码可能会一样，目前的处理方式是相同的末级科目编码辅助项都一样，所以直接取第一个就可以了
        List<SysSubjects> sysSubjects = this.list(new LambdaQueryWrapper<SysSubjects>().eq(SysSubjects::getLastCode, lastCode));
        if (sysSubjects.size() == 0) {
            return null;
        }
        redisTemplate.opsForValue().set(SystemConstants.SUBJECTS_PREFIX+lastCode, sysSubjects.get(0), 1, TimeUnit.HOURS);
        return sysSubjects.get(0);
    }
}
